<!--Canvas鼠标画线组件-->
<template>
  <canvas id="canvas-line" :width="width" :height="height" @mousedown="handlerMousedown" @mouseup="handlerMoseUp"
    >您的浏览器暂不支持Canvas,请切换浏览器!</canvas
  >
  <!--这边放置你需要放置的内容-->
  <div :style="{ zIndex: printFlag ? -99 : 100 }" class="content">
    <slot>请放置你需要放置的内容!</slot>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, ref } from 'vue'
const width = ref<Number>(1920)
const height = ref<Number>(1080)
// 是否允许进行画线
let printFlag = ref<boolean>(false)
// 当前画布对象
let canvasLineDom: any = null
// 当前画布容器对象
let context: any = null
// 是否允许在canvas上进行描线
let allowPrintLine = ref<boolean>(false)
// 画布宽高自适应
onMounted(() => {
  // 第一次加载时获取当前宽高，赋值给画布
  const dom = document.getElementsByTagName('body')
  width.value = dom[0].clientWidth
  height.value = dom[0].clientHeight
  //当窗口大小改变时更改画布宽高
  window.addEventListener('resize', () => {
    width.value = window.innerWidth
    height.value = window.innerHeight - 80
  })
  // 监听键盘enter事件，当用户按下enter时，清空线
  window.addEventListener('keydown', () => {
    printFlag.value = !printFlag.value
    if (canvasValid()) {
      context.reset()
    }
  })
})
// 获取画布对象
onMounted(() => {
  canvasLineDom = document.querySelector('#canvas-line')
  if (canvasValid()) {
    context = canvasLineDom.getContext('2d')
    allowPrintLine.value = true
  }
})
/**
 *  获取鼠标在canvas上的具体坐标
 * @param canvas canvas对象
 * @param x 原x点
 * @param y 原y点
 */
const windowToCanvas = (canvas: any, x: number, y: number) => {
  let rect = canvas.getBoundingClientRect()
  return {
    x: x - rect.left * (canvas.width / rect.width),
    y: y - rect.top * (canvas.height / rect.height),
  }
}

/**
 * 鼠标按下
 * @param e 事件
 */
function handlerMousedown(e: Event) {
  allowPrintLine.value = true
  if (canvasValid()) {
    let ele = windowToCanvas(canvasLineDom, e.clientX, e.clientY)
    let { x, y } = ele
    context.moveTo(x, y)
    canvasLineDom.onmousemove = handlerMouseMove
  }
}

/**
 * 鼠标移动
 * @param e 事件
 */
const handlerMouseMove = (e: Event) => {
  if (canvasValid() && allowPrintLine.value) {
    let ele = windowToCanvas(canvasLineDom, e.clientX, e.clientY)
    let { x, y } = ele
    context.lineTo(x, y)
    context.lineWidth = '5'
    context.strokeStyle = 'rgba(255,0,0,0.87)'
    context.stroke()
  }
}

/**
 * 鼠标松开
 * @param e 事件
 */
function handlerMoseUp(e: Event) {
  if (canvasValid()) {
    allowPrintLine.value = false
  }
}

/**
 * 是否支持canvas
 */
function canvasValid(): boolean {
  return !canvasLineDom || !canvasLineDom.getContext ? false : true
}
</script>

<style scoped lang="scss">
#canvas-line {
  overflow: hidden;
  // 将canvas容器背景设为透明
  background-color: rgba(0, 0, 0, 0);
  margin: 0px;
  padding: 0px;
}
.content {
  overflow: hidden;
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
}
</style>
